//
//  ImagePlayer.swift
//  GifUsage
//
//  Created by han on 2020/12/30.
//  Copyright © 2020 Ting Han. All rights reserved.
//

import UIKit

class ImagePlayer {
    var images = [ImageModel]()
    var defaultDuration: TimeInterval = 0.125
    
    weak var containerView: UIImageView?
    
    var isPlaying: Bool = false
    
    func play() {
        isPlaying = true
        startAnimating()
        containerView?.image = currentImage
    }
    
    func pause() {
        isPlaying = false
        stopAnimating()
    }
    
    init(containerView: UIImageView) {
        self.containerView = containerView
        setupDisplayLink()
        attachDisplayLink()
    }
    
    func onScreenUpdate() {
        guard images.count > 0 else { return }
        if shouldChangeImage(duration: displayLink!.duration) {
            containerView?.image = currentImage
        }
    }
    
    var imageCount: Int {
        images.count
    }
    var currentIndex: Int = 0
    
    var currentDuration: TimeInterval {
        images[safe: currentIndex]?.duration ?? defaultDuration
    }
    
    var currentImage: UIImage {
        images[safe: currentIndex]?.image ?? UIImage()
    }
    
    var displayLink: CADisplayLink?
    var timeSinceLastImageChange: TimeInterval = 0.0
   
    deinit {
        displayLink?.invalidate()
    }
}

extension ImagePlayer {
    
    func shouldChangeImage(duration: TimeInterval) -> Bool {
        timeSinceLastImageChange += min(1, duration)
        if currentDuration > timeSinceLastImageChange {
          return false
        } else {
            timeSinceLastImageChange -= currentDuration
            incrementCurrentImageIndex()
           return true
        }
    }
    
    func incrementCurrentImageIndex() {
        currentIndex += 1
        currentIndex %= imageCount
    }
    
}

extension ImagePlayer {
    private  func setupDisplayLink() {
        displayLink = CADisplayLink(target: DisplayLinkProxy(target: self), selector: #selector(DisplayLinkProxy.onScreenUpdate))
        displayLink!.isPaused = true
    }
    
    private func attachDisplayLink() {
        displayLink?.add(to: .main, forMode: RunLoop.Mode.common)
    }
    
    var isAnimating: Bool {
        return displayLink != nil && displayLink?.isPaused == false
    }
    
    func startAnimating() {
        displayLink?.isPaused = false
    }
    
    func stopAnimating() {
        displayLink?.isPaused = true
    }
    
}

class ImageModel: NSObject {
    var image: UIImage
    var duration: TimeInterval?
    
    init(image: UIImage, duration: TimeInterval?) {
        self.image = image
        self.duration = duration
        super.init()
    }
}

fileprivate class DisplayLinkProxy {
    private weak var target: ImagePlayer?
    init(target: ImagePlayer) {
        self.target = target
    }
    
    @objc func onScreenUpdate() {
        target?.onScreenUpdate()
    }
}



